package com.example.mysql.学习笔记.高级.数据库的优化之索引.索引优化与查询优化;

public class 淘宝的数据库索引的设计 {
}
/**
 * 大部分人的回答如此自信:用8字节的BIGINT做主键，而不要用INT。错!
 * 这样的回答，只站在了数据库这一层，而没有从业务的角度思考主键。
 * 主键就是一个自增ID吗?
 * 站在 2022 年的新年档口，用自增做主键,架构设计上可能连及格都拿不到。
 *
 * 13.1自增ID的问题
 * 自增ID做主键，简单易懂，几乎所有数据库都支持自增类型,只是实现上各自有所不同而已。
 * 自增ID除 了简单，其他都是""缺点""，总体来看存在以下几方面的问题:
 * 1.可靠性不高
 *  存在自增ID回溯的问题,这个问题直到最新版本的MySQL 8.0才修复。
 * 2.安全性不高
 * 对外暴露的接口可以非常容易猜测对应的信息。
 * 比如: /User/1/这样的接口， 可以非常容易猜测用户ID的值为多少，
 *      总用户数量有多少，也可以非常容易地通过接口进行数据的爬取。
 * 3.性能差
 *  自增ID的性能较差，需要在数据库服务器端生成。
 * 4.交互多
 *  业务还需要额外执行一次类似 last_insert_id() 的函数才能知道刚才插入的自增值，
 *  这需要多一次的网络交互。在海量并发的系统中，多1条SQL,就多一次性能 上的开销。
 * 5.局部唯一性
 * 最重要的一点，自增ID是局部唯一，只在当前数据库实例中唯一, 而不是全局唯一,
 * 在任意服务器间都是唯一的。对于目前分布式系统来说，这简直就是體梦。
 *
 * 13.2 业务字段做主键  不行
 * 为了能够唯一地标识一个会员的信息，需要为会员信息表设置一个主键。
 * 那么,怎么为这个表设置主键，才能达到我们理想的目标呢?
 * 这里我们考虑业务字段做主键。
 * 所以，建议尽量不要用跟业务有关的字段做主键。
 * 毕竟,作为项目设计的技术人员,我们谁也无法预测在项目的整个生命周期中，
 * 哪个业务字段会因为项目的业务需求而有重复,或者重用之类的情况出现。
 * 经验:
 * 刚开始使用MySQL时，很多人都很容易犯的错误是喜欢用业务字段做主键，
 * 想当然地认为了解业务需求，但实际情况往往出乎意料，而更改主键设置的成本非常高。
 *
 *
 */

/**
 * 13.4推荐的主键设计
 * 非核心业务:对应表的主键自增ID,如告警、日志、监控等信息。
 * 核心业务:主键设计至少应该是全局唯一且是单调递增。
 *         全局唯一保证在各系统之间都是唯一的, 单调递增是希望插入时不影响数据库性能。
 *         这里推荐最简单的一种主键设计: UUID。
 * UUID的特点:  字符串
 * 全局唯一,占用36字节，数据无序，插入性能差。
 * MySQL数据库的UUID组成如下所示:
 * UUID = 时间+UUID版本(16 字节)-时钟序列(4 字节)- MAC地址(12 字节)
 * 为什么UUID是全局唯一的?
 * 在UUID中时间部分占用60位,存储的类似TIMESTAMP的时间戳，
 * 但表示的是从1582-10-15 00: 00: 00.00到现在的100ns的计数。
 * 可以看到UUID存储的时间精度比 TIMESTAMPE 更高， 时间维度发生重复的概率降低到1/100ns。
 * 时钟序列是为了避免时钟被回拨导致产生时间重复的可能性。MAC地址用于全局唯一。
 * 为什么UUID占用36个字节?
 *    UUID根据字符串进行存储,设计时还带有无用 "-" 字符串,因此总共需要36个字节。
 * 为什么UUID是随机无序的呢?
 *    因为UUID的设计中，将时间低位放在最前面，而这部分的数据是一直在变化的， 并且是无序。
 *
 * 改造UUID
 *   若将时间高低位互换，则时间就是单调递增的了，也就变得单调递增了。
 *   MySQL 8.0可以更换时间低位和时间高位的存储方式，这样UUID就是有序的UUID了。
 *   MySQL 8.0还解决了UUID存在的空间占用的问题，除去了UUID字符串中无意义的"字符串，
 *   并且将字符串用二进制类型保存，这样存储空间降低为了16字节。
 *
 *   在实际业务使用中有序UUID在业务端就可以生成。还可以进一步减少SQL的交互次数。
 *
 */
